<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>js单例模式</title>
	</head>
	<body>
		<style type="text/css">
			* {margin: 0;padding: 0;}
			.qqcontainer {border: 1px black solid;width: 200px;height: 200px;margin: 0 auto;}
		</style>
		
		<button id="btnCreateDiv">创建单框</button><br />
		
		<script type="text/javascript">
			var Brower = function(kindName) {
				this.kindName = kindName;
				this.object = null;
				//对象方法创建函数
				this.writeKindName = function(){
					document.write(this.kindName + "</br>");
				};
			};

			//
		/* creatBrower()类方法创建函数 */
			Brower.creatBrower = function(kindName){
				if(this.object==null){
					var brower = new Brower(kindName);
					this.object = brower;
					return brower;
				}else{
					return this.object;
				}
			}

		/* creatBrower()原型方法创建函数 */
			/* Brower.prototype.creatBrower = function(kindName){
				if(this.object==null){
					var brower = new Brower(kindName);
					this.object = brower;
					return brower;
				}else{
					return this.object;
				}
			};
			//此种方式js报错: Brower.creatBrower is not a function */


			var brower1 = Brower.creatBrower("kind1");
			brower1.writeKindName();
			var brower2 = Brower.creatBrower("kind2");
			brower2.writeKindName();


			/* 重点: js对象方法，类方法，原型方法的区别 */
			var People = function(name) {
				this.name = name;
				//对象方法
				this.Introduce = function() {
					console.log("My name is " + this.name);
				};
			};
			//类方法
			People.Run = function() {
				console.log("I can run.");
			};
			//原型方法
			People.prototype.sayName = function() {
				console.log("I am " + name);
			};

			//测试
			var people1 = new People("Lin")
			people1.Introduce(); //对象方法需要通过实例化对象去调用
			people1.sayName(); //原型方法需要通过实例化对象去调用

			/* 注: 重点
			1、对象方法包括构造函数中的方法以及构造函数原型上面的方法；
			2、类方法，其实这里的类就是一个函数，在js中由于函数也是一个对象，所以可以为函数添加属性以及方法，这种方法在node中用的比较多；
			3、原型方法一般用于对象实例共享，比如Person.prototype.sayName=function(){console.log(this.name);};在原型上面添加该方法，就能实现共享。
				这样就不用每一次初始化一个实例的时候，为其分配相应的内存了。*/

		/* 透明单例模式 */
			//创建一个单例的界面元素
			//重点：透明单例的主要知识运用点: 运用了js闭包的一些特性,如: 全局变量和局部变量重名时,在闭包内,局部变量会替代全局变量生效.
			var CreatDiv = (function() {
				var instance; //instance n.实例 vt.举例子
				if (instance) {
					return instance;
				}
				var CreatDiv = function(html) {
					this.html = html;
					this.init();
					return instance = this;
				};
				
				CreatDiv.prototype.init = function(){
					var div = document.createElement("div");
					div.innerHTML = this.html;
					document.body.appendChild(div);
				};
				return CreatDiv;
			})()
				/* 使用(function(){})() 立即执行函数，是为了初始化CreatDiv对象构造函数 */
			var a = new CreatDiv("div1");
			var b = new CreatDiv("div2");
			
			// alert(a === b);
			
		/* 惰性单例 */
			
			var qqWindow = function(argus){
				this.title = argus.title;
				this.init();
			}
			qqWindow.prototype.init = function(){
				var divObj = document.createElement("div");
					divObj.setAttribute("class","qqcontainer");
					document.body.appendChild(divObj);
			}
			
			document.getElementById("btnCreateDiv").onclick = (function(){
				var argus = {"title":"QQ登陆"}
				var qqcontainer = null;
				return function(){
					if(!qqcontainer){
						qqcontainer = new qqWindow(argus);
						console.log(qqcontainer.title)
					}
					return qqcontainer;
				}
			})()
		/*  */
		</script>
	</body>
</html>
